/**
  ******************************************************************************
  * @file
  * @brief
  * @author luffy
  * @version V1.0.0
  * @date 2022/11/29
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "dev_tca6416.h"

/* Private defines -----------------------------------------------------------*/
#define INPUT0_PORT_REG         0x00
#define INPUT1_PORT_REG         0x01

#define OUTPUT0_PORT_REG        0x02
#define OUTPUT1_PORT_REG        0x03

#define POLARITY0_REG           0x04
#define POLARITY1_REG           0x05

#define CONFIG0_REG             0x06
#define CONFIG1_REG             0x07

/* Private Struct  -----------------------------------------------------------*/

/* Private enum    -----------------------------------------------------------*/

/* Private Variable  ---------------------------------------------------------*/
//Pointer

//Array

//Const

/* Private function prototypes -----------------------------------------------*/

/***********************************************************************************
 * @brief 
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static int Tca6416_Check(dev_tca6416_t *this)
{
    int ret;

    ret = this->private.i2c.Check(&this->private.i2c, this->SLAVE_ADDR);
    if(ret < 0){
        return -1;
    }

    return 0;
}
/***********************************************************************************
 * @brief 
 * ex:   设置IO口读写模式
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static void Tca6416_ModeSetBit(dev_tca6416_t *this, tca6416_mode_e mode, uint16_t bit)
{
    uint8_t data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
//    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, CONFIG0_REG, data, 2) < 0){
//        ;
//    }

    if(mode == TCA6416_INPUT){
        data[1] |= (uint8_t)((uint16_t)bit >> 8);
        data[0] |= (uint8_t)((uint16_t)bit >> 0);
    }
    else{
        data[1] &= (uint8_t)(~(uint16_t)bit >> 8);
        data[0] &= (uint8_t)(~(uint16_t)bit >> 0);        
    }

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Write(&this->private.i2c, this->SLAVE_ADDR, CONFIG0_REG, data, 2) < 0){
        ;
    }
}

/***********************************************************************************
 * @brief 
 * ex:  val：1：设置高电平，0：设置低电平；bit：eg.TCA6416_P00
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static void Tca6416_WriteBit(dev_tca6416_t *this, uint8_t val, uint16_t bit)
{	
    uint8_t data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
        ;
    }

    if(val){
        data[1] |= (uint8_t)((uint16_t)bit >> 8);
        data[0] |= (uint8_t)((uint16_t)bit >> 0);
    }
    else{
        data[1] &= (uint8_t)(~(uint16_t)bit >> 8);
        data[0] &= (uint8_t)(~(uint16_t)bit >> 0);        
    }

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Write(&this->private.i2c, this->SLAVE_ADDR, OUTPUT0_PORT_REG, data, 2) < 0){
        ;
    }
}

/***********************************************************************************
 * @brief 
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
static uint8_t Tca6416_ReadBit(dev_tca6416_t *this, tca6416_pin_e bit)
{
    uint8_t data[2];

    // 错误时重运行，中断或线程打断操作时可以进行重发
    while(this->private.i2c.Read(&this->private.i2c, this->SLAVE_ADDR, INPUT0_PORT_REG, data, 2) < 0){
		;
    }

    data[1] &= (uint8_t)((uint16_t)bit >> 8);
    data[0] &= (uint8_t)((uint16_t)bit >> 0);

    if(data[0] != 0 && data[1] != 0){
        return 1;
    }

    return 0;
}

/***********************************************************************************
 * @brief 
 * ex:
 * @par  
 * None
 * @par 
 * None
 * @retval 
 **********************************************************************************/
int Dev_Tca6416_Init(dev_tca6416_t *this)
{
    this->private.i2c.PIN_SDA        = this->PIN_SDA;
    this->private.i2c.PIN_SCL        = this->PIN_SCL;
    this->private.i2c.SPEED          = I2C_SPEED_SLOW;
    this->private.i2c.WIDTH          = I2C_WIDTH_BYTE;
    this->private.i2c.ACK_TIMEOUT    = I2C_TIMEOUT_STOP;
    this->private.i2c.ACK_WAIT_US    = 100;
	
    if(Drv_I2c_Init(&this->private.i2c) < 0){
        return -1;
    }

    this->Check         = Tca6416_Check;
    this->WriteBit      = Tca6416_WriteBit;
    this->ModeSetBit    = Tca6416_ModeSetBit;
    this->ReadBit       = Tca6416_ReadBit;
	
	Tca6416_ModeSetBit(this,TCA6416_OUTPUT,0xFFFF);  //设置输出模式
	
	Tca6416_WriteBit(this, 0, TCA6416_P00);
	
	Tca6416_WriteBit(this, 1, TCA6416_P01);
	
	return 0;
}


